﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using QunProject.Common;

namespace QunProject.Server.Controllers
{
    public class ServerController : BaseController
    {
        /// <summary>
        /// 统一接口调用
        /// </summary>
        /// <param name="MethodName"></param>
        /// <returns></returns>
        [ValidateInput(false)]
        public ActionResult Index(string MethodName)
        {
            if (string.IsNullOrWhiteSpace(MethodName))
                return Json(Result.Fail("程序错误"), JsonRequestBehavior.AllowGet);
            Type iserver = typeof(Interface.IServer);
            var methodes = iserver.GetMethods();
            MethodInfo method = methodes.FirstOrDefault(x => x.Name.Equals(MethodName));
            if (method == null)
                return Json(Result.Fail("接口名错误"), JsonRequestBehavior.AllowGet);
            // 获取参数
            object _server = Activator.CreateInstance<Interface.Server>();
            List<object> parametersValues = new List<object>();
            JObject queryDiction = new JObject();
            var methodParameters = method.GetParameters();
            switch (Request.RequestType)
            {
                case "POST":
                    if (Request.Form.Count > 0)//排除文件上传
                    {
                        try
                        {
                            var type = Request.ContentType;
                            if (type != "application/x-www-form-urlencoded")
                            {
                                methodParameters.ToList().ForEach(a =>
                                {
                                    var firstOrDefault = Request.Form.AllKeys.FirstOrDefault(o => o.Contains(a.Name));
                                    if (firstOrDefault != null)
                                    {
                                        queryDiction.Add(a.Name, Request[firstOrDefault]);
                                    }
                                    else
                                    {
                                        queryDiction.Add(a.Name, null);
                                    }

                                });
                            }
                            else
                            {
                                var form = Request.Form[0];
                                var querydiction2 = (JObject)JsonConvert.DeserializeObject(form);
                                IEnumerable<JProperty> properties = querydiction2.Properties();
                                methodParameters.ToList().ForEach(a =>
                                {
                                    var firstOrDefault = properties.FirstOrDefault(o => o.Name == a.Name);
                                    if (firstOrDefault != null)
                                    {
                                        queryDiction.Add(a.Name, firstOrDefault.Value);
                                    }
                                    else
                                    {
                                        queryDiction.Add(a.Name, null);
                                    }

                                });
                            }
                        }
                        catch (Exception e)
                        {
                            return Json(Result.Fail(e.Message), JsonRequestBehavior.AllowGet);
                        }
                    }
                    break;
                case "GET":
                    methodParameters.ToList().ForEach(a =>
                    {
                        queryDiction.Add(a.Name, Request[a.Name]);
                    });
                    break;
                default:
                    return Json(Result.Fail("HTTP传输方式错误"), JsonRequestBehavior.AllowGet);
            }
            // 构造传入参数
            string paramter = "";
            List<object> parameters = new List<object>();
            methodParameters.ToList().ForEach(a =>
            {
                if (!a.ParameterType.Name.Contains("Nullable") && !a.HasDefaultValue && (queryDiction[a.Name] == null || string.IsNullOrEmpty(queryDiction[a.Name].ToString())))
                {
                    paramter += "参数 [" + a.Name + "] 不能为空";
                }
                else
                {
                    try
                    {
                        //判断是否为nullable泛型类 
                        if (a.ParameterType.IsGenericType && a.ParameterType.GetGenericTypeDefinition() == typeof(Nullable<>))
                        {
                            if ((queryDiction[a.Name] == null || string.IsNullOrEmpty(queryDiction[a.Name].ToString())))
                            {
                                if (a.HasDefaultValue)
                                {
                                    parameters.Add(a.DefaultValue);
                                }
                                else
                                {
                                    parameters.Add(null);
                                }
                            }
                            else
                            {
                                //如果tp为nullable类，声明一个NullableConverter类，该类提供从Nullable类到基础基元类型的转换
                                NullableConverter nullableConverter = new NullableConverter(a.ParameterType);
                                var ovalue = nullableConverter.ConvertFromString(queryDiction[a.Name].ToString());
                                parameters.Add(ovalue);
                            }
                        }
                        else if ("article|classify|member|reply|resource|special|sys_menu|sys_user|template".IndexOf(a.ParameterType.Name) > -1)
                        {
                            switch (a.ParameterType.Name)
                            {
                                case "article":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.article>(queryDiction[a.Name].ToString()));
                                    break;
                                case "classify":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.classify>(queryDiction[a.Name].ToString()));
                                    break;
                                case "member":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.member>(queryDiction[a.Name].ToString()));
                                    break;
                                case "reply":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.reply>(queryDiction[a.Name].ToString()));
                                    break;
                                case "resource":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.resource>(queryDiction[a.Name].ToString()));
                                    break;
                                case "special":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.special>(queryDiction[a.Name].ToString()));
                                    break;
                                case "sys_menu":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.sys_menu>(queryDiction[a.Name].ToString()));
                                    break;
                                case "sys_user":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.sys_user>(queryDiction[a.Name].ToString()));
                                    break;
                                case "template":
                                    parameters.Add(JsonConvert.DeserializeObject<Model.template>(queryDiction[a.Name].ToString()));
                                    break;
                                default:
                                    parameters.Add(null);
                                    break;
                            }
                        }
                        else
                        {
                            if (queryDiction[a.Name] == null || string.IsNullOrEmpty(queryDiction[a.Name].ToString()))
                            {
                                if (a.HasDefaultValue)
                                {
                                    parameters.Add(a.DefaultValue);
                                }
                            }
                            else
                            {
                                object value = null;
                                switch (a.ParameterType.Name)
                                {
                                    case "Guid":
                                        value = Guid.Parse(queryDiction[a.Name].ToString());
                                        break;
                                    default:
                                        value = Convert.ChangeType(queryDiction[a.Name].ToString(), a.ParameterType);
                                        break;
                                }
                                parameters.Add(value);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        paramter += "[" + a.Name + "] 参数异常：" + e.Message;
                    }
                }
            });
            // 如果存在异常信息
            if (!string.IsNullOrEmpty(paramter))
                return Json(Result.Fail(paramter), JsonRequestBehavior.AllowGet);
            // 执行方法
            try
            {
                var resultValue = method.Invoke(_server, parameters.ToArray());
                return Json(resultValue, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                if (ex.InnerException.Message == Common.ConstantCode.Result.result_login_outtime)
                {
                    return Json(Result.OutTime(), JsonRequestBehavior.AllowGet);
                }
                else
                {
                    return Json(Result.Fail(ex.Message), JsonRequestBehavior.AllowGet);
                }
            }
        }
    }
}